package com.alexis.portknocking;

import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.util.Log;

public class Knock {
	private String localaddr;
	
	public Knock(Context ctx) {
		// TODO: Manage when the user is disconnected
		
		ConnectivityManager connectManager = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
		if (connectManager.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
			Log.i("PortKnocker", "Using WiFi, will get its IP address ...");
			WifiManager wifi = (WifiManager)ctx.getSystemService(Context.WIFI_SERVICE);
			
			int ipint = wifi.getConnectionInfo().getIpAddress();
			byte[] ip = new byte[4];
			for (int i = 0; i < 4; i++) {
				ip[i] = (byte)((ipint >> i*8) & 0xFF);
			}
			
			try {
				localaddr = InetAddress.getByAddress(ip).getHostAddress();
			} catch (UnknownHostException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		} else {
			Log.i("PortKnocker", "Using mobile network, will use a hack to determine local ip address ...");
			
			try {
				Socket tmps = new Socket("www.google.com",80);
				localaddr = tmps.getLocalAddress().getHostAddress();
				tmps.close();
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		Log.i("PortKnocker", "My local ip address is "+((localaddr == null)?"unknown (no ip address found)":localaddr));
	}
	
	public boolean doKnock(String host, int port) {
		try {
			Socket s;
			s = new Socket();
			
			if (localaddr != null)
				s.bind(new InetSocketAddress(localaddr, 0));
			
			Log.i("PortKnocker", String.format("bind() to %s:%d", s.getLocalAddress().getHostName(),
					s.getLocalPort()));
			
			s.connect(new InetSocketAddress(host, port));
			
			s.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
			return false;
		} catch (ConnectException e) {
			// We dismiss "connection refused" as knockd operates at link-layer
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		
		return true;
	}
}
